package awk.script.javassist.method04.proxy.javassist;

import javassist.Modifier;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yujianlong
 * @create 2021-03-29 17:16
 **/
public class JavassistProxy  {
	public static <T> T getProxy(Class<T> clazz,Class<?>[] paramTypes, Object[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

		// 代理工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		// 设置需要创建子类的父类
		proxyFactory.setSuperclass(clazz);

		return  (T) proxyFactory.create(paramTypes, args, gethandler());
	}


	public static MethodHandler gethandler(){

		MethodHandler handler = new MethodHandler() {

			/**
			 * @param obj 原来的对象
			 * @param method  这个是原来类的方法
			 * @param process JavaAssist获取的进程，是修改后的类方法
			 * @param args 参数
			 */
			@Override
			public Object invoke(Object obj, Method method, Method process, Object[] args) throws Throwable {


				String methodName = method.getDeclaringClass().getName();

				System.out.println("类名：" + method.getClass().getName());
				System.out.println("方法：" + methodName);
				System.out.println("入参个数：" + args.length);
				boolean isStatic = Modifier.isStatic(method.getModifiers());
				System.out.println("入参[类型]："+Stream.of(method.getParameterTypes()).map(c->c.getName()).collect(Collectors.joining(",")));
				System.out.println("入参："+Stream.of(args).map(c-> Objects.toString(c,"")).collect(Collectors.joining(",")));
				System.out.println("方法类型：" + (isStatic ? "静态方法" : "非静态方法"));
				System.out.println("出参[类型]：" + method.getReturnType());
				Object result = null;
				long startTime = System.nanoTime();
				result = process.invoke(obj, args);
				long endTime = System.nanoTime();
				System.out.println("执行时间：" + (endTime-startTime));
				System.out.println("执行结果：" + Objects.toString(result));
				return result;
			}
		};
		return handler;
	}


}
